package com.mangofactory.aop.configuration
{
	
	import com.mangofactory.aop.aspects.Aspect;
	import com.mangofactory.aop.interceptors.AspectInvokingInterceptor;
	
	import org.as3commons.reflect.MetaData;
	import org.as3commons.reflect.Method;
	import org.as3commons.reflect.Type;
	
	public class MetatagProxyPolicy implements ProxyPolicy
	{
		private var registry:Object = {};
		
		public function register(metatagName:String, aspect:Aspect):void
		{
			registry[metatagName] = aspect;
		}

		private function containsAspectForMetadata(metadata:MetaData):Boolean
		{
			return getAspectForMetadata(metadata) != null;
		}
		private function getAspectForMetadata(metadata:MetaData):Aspect
		{
			return registry[metadata.name] as Aspect;
		}

		public function requiresProxy(sourceClass:Class):Boolean
		{
			var type:Type = Type.forClass(sourceClass);
			return getMethodsToProxy(type).length > 0;
		}

		public function getAspectsForMethod(method:Method):Vector.<Aspect>
		{
			var result:Vector.<Aspect> = new Vector.<Aspect>();
			for each (var metaData:MetaData in method.metaData)
			{
				var aspect:Aspect = getAspectForMetadata(metaData);
				if (aspect)
					result.push(aspect);
			}
			return result;
		}
		
		public function getMethodsToProxy(type:Type):Vector.<Method>
		{
			var result:Vector.<Method> = new Vector.<Method>();
			for each (var method:Method in type.methods)
			{
				for each (var metadata:MetaData in method.metaData)
				{
					if (containsAspectForMetadata(metadata) && result.indexOf(method) == -1)
					{
						result.push(method)
					}
				}
			}
			return result;
		}
	}
}


